/**
 * 
 */
package org.gbif.agi.service.impl;

import java.util.List;

import org.gbif.agi.model.Genus;
import org.gbif.agi.service.GenusManager;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

/**
 * @author timrobertson
 */
public class GenusManagerImpl extends HibernateDaoSupport implements GenusManager {
	public static final int SEARCH_RESULTS = 25;

	@SuppressWarnings("unchecked")
	public Genus find(long id) {
		return (Genus)getHibernateTemplate().load(Genus.class, id);
	}

	@SuppressWarnings("unchecked")
	public List<Genus> findAll() {
		return (List<Genus>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session) {
						Query query = session.createQuery("select g from Genus g order by g.fullScientificName");
						query.setMaxResults(SEARCH_RESULTS);
						return query.list();						
					}});
	}

	@SuppressWarnings("unchecked")
	public List<Genus> find(final long datasourceId, final long lftId, final long rgtId) {
		return (List<Genus>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session) {
						Query query = session.createQuery("select g from Genus as g inner join g.genusTaxa as gt where gt.agiDatasourceId=:id and gt.taxonLft between :lft and :rgt order by g.fullScientificName");
						query.setMaxResults(SEARCH_RESULTS);
						query.setLong("id", datasourceId);
						query.setLong("lft", lftId);
						query.setLong("rgt", rgtId);
						return query.list();						
					}});		
	}

	@SuppressWarnings("unchecked")
	public List<Genus> find(String startsWith) {
		return find(startsWith, SEARCH_RESULTS);
	}
	
	@SuppressWarnings("unchecked")
	public List<Genus> find(final String startsWith, final int results) {
		return (List<Genus>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session) {
						Query query = session.createQuery("select g from Genus g where g.fullScientificName like :start order by g.fullScientificName");
						query.setString("start", startsWith + "%");
						query.setMaxResults(results);
						return query.list();						
					}});
	}
	
	public int count(final String startsWith) {
		Long count = (Long) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session) {
						Query query = session.createQuery("select count(*) from Genus g where g.fullScientificName like :start");
						query.setString("start", startsWith + "%");
						return query.uniqueResult();						
					}});
		// will not exceed this ;o)
		return count.intValue();
	}
	
	
	@SuppressWarnings("unchecked")
	public List<Genus> find(final String startsWith, String sortName,
			final boolean sortAsc, final int startAt, final int results) {
		String tempSort = null;
		if ("AUTHORSHIP".equalsIgnoreCase(sortName)) {
			tempSort = "g.authorship";
		} else if ("CANONICAL".equalsIgnoreCase(sortName)) {
			tempSort = "g.canonical";
		} else {
			tempSort = "g.fullScientificName";
		}
		final String sort = tempSort;
		List<Genus> genera =   (List<Genus>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session) {
						String asc = "asc";
						if (!sortAsc) {
							asc = "desc";
						}
						System.out.println("ASC: " + asc);
						Query query = session.createQuery("select g from Genus g where g.fullScientificName like :start order by " + sort + " " + asc);
						query.setString("start", startsWith + "%");
						query.setFirstResult(startAt);
						query.setMaxResults(results);		
						return query.list();						
					}});
		return genera;		
	}
	
	
	public void remove(long id) {
		Genus genus = find(id);
		if (genus != null) {
			getHibernateTemplate().delete(genus);
		}
	}
	
	public void remove(Genus genus) {
		getHibernateTemplate().save(genus);
	}
	
	public void save(Genus genus) {
        if (genus.getId() == null) {
        	getHibernateTemplate().save(genus);
        } else {
        	getHibernateTemplate().update(genus);
        }
	}
}
